package com.example.framework;

import com.example.utils.SortedListOf;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import java.util.List;

/**
 * Class manipulate with Add New Contact page
 */
public class ContactHelper extends WebDriverHelper {

    public static final boolean CREATION = true;
    public static final boolean MODIFICATION = false;
    private SortedListOf<ContactData> cachedContacts;

    public ContactHelper(HelperManager manager) {
        super(manager);
    }

    public void createContact(ContactData contact){
        manager.getNavigationHelper().gotoAddNewContactPage();
        fillContactCreationForm(contact, CREATION);
        submitContactCreationForm();
        returnToMainPage();
        rebuildCache();
    }

    public void modifyContact(int index, ContactData contact){
        gotoEditContactFormByIndex(index);
        fillContactCreationForm(contact, MODIFICATION);
        submitModification();
        returnToMainPage();
        rebuildCache();
    }

    public void deleteContactByIndex(int index) {
        manager.getNavigationHelper().gotoHomePage();
        WebElement contact = getContactByIndex(index);
        selectContact(contact);
        pressEditButton(contact);
        pressDeleteButton();
        returnToMainPage();
        rebuildCache();
    }

    public void searchContact(String searchString) {
        manager.getNavigationHelper().gotoHomePage();
        typeTextInSearchBox(searchString);
    }

    public ContactHelper selectContactByIndex(int index) {
        WebElement contact = getContactByIndex(index);
        selectContact(contact);
        return this;
    }

    /*
    Index should be 0-based index.
    That is you need to delete the first group index should be = 0.
    */
    public ContactHelper addToGroupByIndex(int index) {
        click(By.cssSelector("select[name='to_group'] option:nth-child(" + (index + 1) + ")"));
        click(By.cssSelector("input[name='add']"));
        return this;
    }

    public SortedListOf<ContactData> getAllContacts() {
        if (cachedContacts == null){
            rebuildCache();
        }
        return cachedContacts;
    }

    public SortedListOf<ContactData> getFoundContacts() {
        List<WebElement> contactListFromUI = driver.findElements(By.cssSelector("tr[name='entry'][style='']"));
        return convertUIContactListToContactDataList(contactListFromUI);
    }

    private void rebuildCache() {
        manager.getNavigationHelper().gotoHomePage();
        List<WebElement> contactListFromUI = driver.findElements(By.cssSelector("tr[name='entry']"));
        cachedContacts = convertUIContactListToContactDataList(contactListFromUI);
    }

    //-------------------------------------------
    // Internal methods
    private void fillContactCreationForm(ContactData contactData, boolean formType) {
        inputTextToEditBox(By.name("firstname"), contactData.getFirstName());
        inputTextToEditBox(By.name("lastname"), contactData.getLastName());
        inputTextToEditBox(By.name("address"), contactData.getAddress());
        inputTextToEditBox(By.name("home"), contactData.getHomePhone());
        inputTextToEditBox(By.name("mobile"), contactData.getMobilePhone());
        inputTextToEditBox(By.name("work"), contactData.getWorkPhone());
        inputTextToEditBox(By.name("email"), contactData.getEmail());
        inputTextToEditBox(By.name("email2"), contactData.getSecondEmail());
        selectDay(contactData.getBirthdayDay());
        selectMonth(contactData.getBirthdayMonth());
        inputTextToEditBox(By.name("byear"), contactData.getBirthdayYear());
        if (formType == CREATION){
            selectDropdownListItemByText(By.name("new_group"), contactData.getGroupName());
        } else {
            if (driver.findElements(By.name("new_group")).size() != 0){
                throw new Error("Contact modification form contains Group dropdown list");
            }
        }
        inputTextToEditBox(By.name("address2"), contactData.getSecondAddress());
        inputTextToEditBox(By.name("phone2"), contactData.getSecondHomePhone());
    }

    private void selectDay (String day){
        // index for selector should be [3 - 33]
        int index = Integer.parseInt(day) + 1;
        click(By.cssSelector("select[name='bday'] option:nth-child("+ index +")"));
    }

    private void selectMonth (String month){
        // index for selector should be [3 - 14]
        int index = Integer.parseInt(month) + 1;
        click(By.cssSelector("select[name='bmonth'] option:nth-child("+ index +")"));
    }

    private void submitContactCreationForm() {
        click(By.name("submit"));
        cachedContacts = null;
    }

    private void returnToMainPage() {
        if (driver.getCurrentUrl().contains("edit.php")
                && driver.findElements(By.linkText("home page")).size() > 0) {
            click(By.linkText("home page"));
        }
    }

    private void typeTextInSearchBox(String text) {
        manager.getNavigationHelper().gotoHomePage();
        inputTextToEditBox(By.name("searchstring"), text);
    }

    private void selectContact(WebElement contact) {
        contact.findElement(By.cssSelector("input[name='selected[]']")).click();
   }

    private void pressEditButton(WebElement contact) {
        contact.findElement(By.cssSelector("a[href*=edit]")).click();
    }

    private void pressDeleteButton(){
        click(By.cssSelector("input[value='Delete']"));
        cachedContacts = null;
    }

    private void gotoEditContactFormByIndex(int index) {
        WebElement contact = getContactByIndex(index);
        selectContact(contact);
        pressEditButton(contact);
    }

    private void submitModification() {
        click(By.cssSelector("input[value='Update']"));
        cachedContacts = null;
    }

    /*
     Index should be 0-based index.
     That is you need to delete the first group index should be = 0.
     */
    private WebElement getContactByIndex(int index){
        //skip the first <tr> element because it's a table header, and converse css-selector to 0-based index
        WebElement contact =  driver.findElement(By.cssSelector("tr[name='entry']:nth-child(" + (index + 2) + ")"));
        return contact;
    }

    private SortedListOf<ContactData> convertUIContactListToContactDataList(List<WebElement> contactListFromUI) {
        SortedListOf<ContactData> contactList = new SortedListOf<ContactData>();
        for (WebElement contactFromUI: contactListFromUI){
            String firstName = contactFromUI.findElement(By.cssSelector("td:nth-child(3)")).getText();
            String lastName = contactFromUI.findElement(By.cssSelector("td:nth-child(2)")).getText();
            String email = contactFromUI.findElement(By.cssSelector("td:nth-child(4) a")).getText();

            ContactData contact = new ContactData()
                    .withFirstName(firstName)
                    .withLastName(lastName)
                    .withEmail(email);

            contactList.add(contact);
        }
        return contactList;
    }
}
